home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Magazine / Online / QMail / source / cdb_seek.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-15  |  1.7 KB  |  96 lines

  1. #include <sys/types.h>
  2. #include <errno.h>
  3. extern int errno;
  4. #include "cdb.h"
  5.  
  6. #ifndef SEEK_SET
  7. #define SEEK_SET 0
  8. #endif
  9.  
  10. int cdb_bread(fd,buf,len)
  11. int fd;
  12. char *buf;
  13. int len;
  14. {
  15.   int r;
  16.   while (len > 0) {
  17.     do
  18.       r = read(fd,buf,len);
  19.     while ((r == -1) && (errno == EINTR));
  20.     if (r == -1) return -1;
  21.     if (r == 0) { errno = EIO; return -1; }
  22.     buf += r;
  23.     len -= r;
  24.   }
  25.   return 0;
  26. }
  27.  
  28. static int match(fd,key,len)
  29. int fd;
  30. char *key;
  31. unsigned int len;
  32. {
  33.   char buf[32];
  34.   int n;
  35.   int i;
  36.  
  37.   while (len > 0) {
  38.     n = sizeof(buf);
  39.     if (n > len) n = len;
  40.     if (cdb_bread(fd,buf,n) == -1) return -1;
  41.     for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0;
  42.     key += n;
  43.     len -= n;
  44.   }
  45.   return 1;
  46. }
  47.  
  48. int cdb_seek(fd,key,len,dlen)
  49. int fd;
  50. char *key;
  51. unsigned int len;
  52. uint32 *dlen;
  53. {
  54.   char packbuf[8];
  55.   uint32 pos;
  56.   uint32 h;
  57.   uint32 lenhash;
  58.   uint32 h2;
  59.   uint32 loop;
  60.   uint32 poskd;
  61.  
  62.   h = cdb_hash(key,len);
  63.  
  64.   pos = 8 * (h & 255);
  65.   if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1;
  66.  
  67.   if (cdb_bread(fd,packbuf,8) == -1) return -1;
  68.  
  69.   pos = cdb_unpack(packbuf);
  70.   lenhash = cdb_unpack(packbuf + 4);
  71.  
  72.   if (!lenhash) return 0;
  73.   h2 = (h >> 8) % lenhash;
  74.  
  75.   for (loop = 0;loop < lenhash;++loop) {
  76.     if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1;
  77.     if (cdb_bread(fd,packbuf,8) == -1) return -1;
  78.     poskd = cdb_unpack(packbuf + 4);
  79.     if (!poskd) return 0;
  80.     if (cdb_unpack(packbuf) == h) {
  81.       if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1;
  82.       if (cdb_bread(fd,packbuf,8) == -1) return -1;
  83.       if (cdb_unpack(packbuf) == len)
  84.     switch(match(fd,key,len)) {
  85.       case -1:
  86.         return -1;
  87.       case 1:
  88.         *dlen = cdb_unpack(packbuf + 4);
  89.         return 1;
  90.     }
  91.     }
  92.     if (++h2 == lenhash) h2 = 0;
  93.   }
  94.   return 0;
  95. }
  96.